from typing import Dict, Optional

from enums.protocol_type import TcpConfig, ProtocolType, RtuConfig
from service.log import log
from service.modbus_client import ModbusClient
from db.controller.db_controller import db_controller


class ClientManager:
    def __init__(self):
        self.client_map: Dict[str, ModbusClient] = {}

    def set_all_client(self):
        device_list = db_controller.device_dao.get_device_list()
        for device in device_list:
            device_name = device['name']
            ip = device['ip']
            port = device['port']
            protocol = device['protocol']
            if protocol == ProtocolType.TCP.value:
                self.add_modbus_tcp_client(device_name, ip, port)
            elif protocol == ProtocolType.RTU_OVER_TCP.value:
                self.add_modbus_rtu_over_tcp_client(device_name, ip, port)
            else:
                return

    def add_modbus_tcp_client(self, device_name: str, ip: str, port: int):
        if device_name not in self.client_map:
            tcp_config = TcpConfig(ip, port, ProtocolType.TCP)
            self.client_map[device_name] = ModbusClient(protocol_type=ProtocolType.TCP, tcp_config=tcp_config,
                                                        rtu_config=None)

    def add_modbus_rtu_over_tcp_client(self, device_name: str, ip: str, port: int):
        if device_name not in self.client_map:
            tcp_config = TcpConfig(ip, port, ProtocolType.RTU_OVER_TCP)
            self.client_map[device_name] = ModbusClient(protocol_type=ProtocolType.RTU_OVER_TCP, tcp_config=tcp_config,
                                                        rtu_config=None)

    def add_modbus_rtu_client(self, device_name: str, port: str, baudrate: int, parity: str,
                              stopbits: int, bytesize: int, timeout: float):
        if device_name not in self.client_map:
            rtu_config = RtuConfig(port, baudrate, parity, stopbits, bytesize, timeout)
            self.client_map[device_name] = ModbusClient(protocol_type=ProtocolType.RTU, tcp_config=None,
                                                        rtu_config=rtu_config)

    def edit_client(self, old_device_name: str, protocol_type: ProtocolType, device_name: str, ip: str,
                    port: int) -> None:
        try:
            self.delete_client(old_device_name)
            if protocol_type == ProtocolType.TCP:
                self.add_modbus_tcp_client(device_name, ip, port)
            elif protocol_type == ProtocolType.RTU_OVER_TCP:
                self.add_modbus_rtu_over_tcp_client(device_name, ip, port)
            else:
                return
        except Exception as e:
            log.error(f"编辑客户端失败: {e}")
            raise e

    def delete_client(self, device_name: str):
        log.info(f"删除客户端: {device_name}")
        if device_name in self.client_map:
            self.client_map[device_name].disconnect()
            del self.client_map[device_name]

    def get_client(self, device_name: str) -> Optional[ModbusClient]:
        if device_name in self.client_map:
            return self.client_map[device_name]
        else:
            return None


client_manager = ClientManager()
client_manager.set_all_client()
